package com.hw.service.task;

import cn.hutool.core.img.ImgUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Assert;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.hw.entity.dto.task.TaskDTO;
import com.hw.entity.po.basic.StoreInfo;
import com.hw.entity.po.shoppingCart.ShoppingCart;
import com.hw.entity.po.sys.SysUser;
import com.hw.entity.po.task.Task;
import com.hw.entity.query.task.TaskQuery;
import com.hw.entity.vo.basic.StoreInfoVO;
import com.hw.entity.vo.task.TaskDetailVO;
import com.hw.entity.vo.task.TaskListVO;
import com.hw.entity.dto.task.TaskTimeDTO;
import com.hw.entity.vo.task.TaskOngoingListVO;
import com.hw.entity.vo.task.TaskTimeVO;
import com.hw.mapper.task.TaskMapper;
import com.hw.model.ResponseResult;
import com.hw.service.basic.StoreInfoService;
import com.hw.service.shoppingCart.ShoppingCartService;
import com.hw.service.sys.SysUserService;
import com.hw.utils.AdminUtils;
import com.hw.utils.JwtUtils;
import org.apache.commons.lang3.ArrayUtils;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.poi.ss.formula.functions.T;
import org.apache.shiro.SecurityUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.LinkedList;
import java.util.List;
import java.util.UUID;

/**
 * 任务表 Service实现类
 *
 * @author xuguang
 * @date 2021-06-28
 */
@Service
public class TaskServiceImpl extends ServiceImpl<TaskMapper, Task> implements TaskService {

    @Autowired
    private SysUserService sysUserService;

    @Autowired
    private StoreInfoService storeInfoService;

    @Autowired
    @Lazy(true)
    private ShoppingCartService shoppingCartService;

    /**
     * 根据点参员获取分页列表
     *
     * @param taskQuery
     * @return
     */
    @Override
    public IPage<TaskListVO> getTaskListByUser(TaskQuery taskQuery) {
        // 获取当前用户
        SysUser currentUser = sysUserService.getOne(AdminUtils.getUserName());
        // 每次查询时先更新状态（权宜之计，最好能在数据库加一个定时事件修改状态）
        QueryWrapper<Task> queryWrapper = new QueryWrapper<>();
        queryWrapper
                .le("c_end_time", LocalDateTime.now())
                .eq("c_status", 0);
        //  第一次查询 将过期点餐状态置为1
        List<Task> expiredTasks = baseMapper.selectList(queryWrapper);
        for (Task expiredTask : expiredTasks) {
            expiredTask.setStatus(1);
            // 将过期点餐的购物车信息逻辑删除
            UpdateWrapper<ShoppingCart> updateWrapper = new UpdateWrapper<>();
            updateWrapper
                    .set("c_deleted", 0)
                    .eq("c_task_id", expiredTask.getTaskId());
            shoppingCartService.update(updateWrapper);
            updateById(expiredTask);
        }

        // 第二次查询 查询分页列表
        QueryWrapper<Task> qw = new QueryWrapper<>();
        qw
                .eq("t.c_deleted", 0);
        // 判断是否有查询参数
        if (taskQuery.getTime() != null) {
            // 处理时间格式
            // 后端传过来的时间是减8的，所以都加上8才等于原来的时间
            taskQuery.setTime(taskQuery.getTime().plusHours(8));
            LocalDateTime dateNight = taskQuery.getTime();
            // +8，并且到这一天的23:59:59
            dateNight = dateNight.plusHours(23).plusMinutes(59).plusSeconds(59);
            qw
                    .ge("t.c_create_time", taskQuery.getTime())
                    .le("t.c_end_time", dateNight);
        }
        if (taskQuery.getStoreId() != null && taskQuery.getStoreId() != "") {
            qw
                    .eq("t.c_store_id", taskQuery.getStoreId());
        }
        if (taskQuery.getTaskTitle() != null && taskQuery.getTaskTitle() != "") {
            qw
                    .like("t.c_task_title", taskQuery.getTaskTitle());
        }
        Page<TaskListVO> page = new Page<>(taskQuery.getPageIndex(), taskQuery.getPageSize());
        IPage<TaskListVO> taskListVOIPage = baseMapper.pageList(page, qw);

        if (taskListVOIPage == null) {
            return null;
        }
        for (TaskListVO record : taskListVOIPage.getRecords()) {
            record.setTotalPrice(getTaskTotalPrice(record.getTaskId()) != null ? getTaskTotalPrice(record.getTaskId()) : 0.0 );
            if (record.getTotalPerson() == 0) {
                // 不能返回空
                record.setAvgPrice(0.0);
            } else {
                record.setAvgPrice(record.getTotalPrice() / record.getTotalPerson());
            }
        }
        return taskListVOIPage;
    }

    /**
     * 根据订单id获取总价格
     *
     * @param taskId
     * @return
     */
    private Double getTaskTotalPrice(String taskId) {
        return baseMapper.getTaskTotalPrice(taskId);
    }

    /**
     * 发起任务
     *
     * @param taskDTO
     */
    @Override
    public ResponseResult<?> generatorTask(TaskDTO taskDTO){
        // 任务id和任务码随机生成
        // 商家id和截止时间可获取到
        // 创建用户可获取到
        // 创建时间为now
        // 其他默认

        if (taskDTO.getEndTime() == null) {
            return ResponseResult.error("截止时间不能为空!");
        }
        // 获取当前用户
        SysUser currentUser = sysUserService.getOne(AdminUtils.getUserName());
        Task task = new Task();
        task.setTaskId(UUID.randomUUID().toString());
        task.setStoreId(taskDTO.getStoreId());

        // 传过来的时间没有设置时区，所以+8
        taskDTO.setEndTime(taskDTO.getEndTime().plusHours(8));
        // 如果前端时间是手动输入，日期会变成1月1日，这时候判断一下，日期不是当天的话就改成当天
        LocalDateTime now = LocalDateTime.now();
        if (taskDTO.getEndTime().getDayOfYear() != now.getDayOfYear()) {
            // 如果日期不对，则最终保存的是now的日期加getEndTime的时分秒
            taskDTO.setEndTime(
                    LocalDateTime.of(
                            now.toLocalDate(),
                            taskDTO.getEndTime().toLocalTime()
                    )
            );
        }
        task.setEndTime(taskDTO.getEndTime());
        task.setCreateId(currentUser.getUserId());
        task.setCreateTime(LocalDateTime.now());
        task.setTaskTitle(taskDTO.getTaskTitle());

        baseMapper.insert(task);

        return ResponseResult.success();
    }

    /**
     * 删除
     *
     * @param taskId
     */
    @Override
    public void delete(String taskId) {
        if (StringUtils.isNotBlank(taskId)) {
            UpdateWrapper<Task> updateWrapper = new UpdateWrapper<>();
            updateWrapper
                    .set("c_deleted", 1)
                    .eq("c_task_id", taskId);
            update(updateWrapper);

            // 将删除状态置为1之后，原有的购物车数据数量进行逻辑删除
            Task task = baseMapper.selectOne(new QueryWrapper<Task>().eq("c_task_id", taskId));
            UpdateWrapper<ShoppingCart> shoppingCartUpdateWrapper = new UpdateWrapper<>();
            shoppingCartUpdateWrapper
                    .set("c_deleted", 1)
                    .eq("c_task_id", task.getTaskId());
            shoppingCartService.update(shoppingCartUpdateWrapper);

        }
    }

    /**
     * 根据订单id获取订单详情
     *
     * @param taskId
     * @return
     */
    @Override
    public TaskDetailVO getTaskDetail(String taskId) {
        if (StringUtils.isBlank(taskId)) {
            return null;
        }
        TaskDetailVO vo = baseMapper.getTaskDetail(taskId);
        // 处理图片
//        if (ArrayUtils.isNotEmpty(vo.getStoreImg())) {
//            String avatarBase64 = ImgUtil.toBase64(ImgUtil.toImage(vo.getStoreImg()), "png");
//            vo.setStoreImgVO(avatarBase64);
//            vo.setStoreImg(null);
//        }
        return vo;
    }

    /**
     * 修改时间(需要判断时间是否过期)
     *
     * @param taskTimeDTO
     */
    @Override
    public ResponseResult<?> updateTime(TaskTimeDTO taskTimeDTO) {

        if (taskTimeDTO.getEndTime() == null) {
            return ResponseResult.error("截止时间不能为空!");
        }

        UpdateWrapper<Task> updateWrapper = new UpdateWrapper<>();
        // 如果要修改的时间比现在的时间还早，说明要在更早终止，不如现在停止，所以是不允许的
        // 前端传回来的时间减了8小时，方便起见，我们将前端时间+8
        taskTimeDTO.setEndTime(taskTimeDTO.getEndTime().plusHours(8));
        // 如果前端时间是手动输入，日期会变成1月1日，这时候判断一下，日期不是当天的话就改成当天
        LocalDateTime now = LocalDateTime.now();
        if (taskTimeDTO.getEndTime().getDayOfYear() != now.getDayOfYear()) {
            // 如果日期不对，则最终保存的是now的日期加getEndTime的时分秒
            taskTimeDTO.setEndTime(
                    LocalDateTime.of(
                            now.toLocalDate(),
                            taskTimeDTO.getEndTime().toLocalTime()
                    )
            );
        }
        if (taskTimeDTO.getEndTime().isBefore(LocalDateTime.now()) ) {
            return ResponseResult.error("该截止时间已过,请往后修改!");
        }
        // 如果时间在当前时间后面，则不用修改其他，只需要正常修改时间就好
        updateWrapper
                .set("c_end_time", taskTimeDTO.getEndTime())
                .eq("c_task_id", taskTimeDTO.getTaskId());
        update(updateWrapper);
        return ResponseResult.success();
    }

    /**
     * 根据订单id获取截止时间
     *
     * @param taskId
     * @return
     */
    @Override
    public TaskTimeVO getEndTime(String taskId) {
        QueryWrapper<Task> queryWrapper = new QueryWrapper<>();
        queryWrapper
                .eq("c_task_id", taskId)
                .eq("c_deleted", 0);

        return baseMapper.getEndTime(queryWrapper);
    }

    /**
     * 提前结束
     *
     * @param taskId
     * @return
     */
    @Override
    public ResponseResult<?> endNow(String taskId) {
        // 直接修改为当前时间，并且将状态改为结束即可
        UpdateWrapper<Task> updateWrapper = new UpdateWrapper<>();
        updateWrapper
                .set("c_end_time", LocalDateTime.now())
                .set("c_status", 1)
                .eq("c_task_id", taskId);
        update(updateWrapper);

        // 假删除购物车信息（设置deleted字段为1）
        shoppingCartService.update(new UpdateWrapper<ShoppingCart>().set("c_deleted", 1).eq("c_task_id", taskId));
        return ResponseResult.success();
    }

//    /**
//     * 判断任务码是否有效
//     *
//     * @param code
//     * @return
//     */
//    @Override
//    public ResponseResult<?> valid(String code) {
//        if (StringUtils.isBlank(code)) {
//            return ResponseResult.error("任务码不能为空！");
//        }
//        code = code.trim();
//        QueryWrapper<Task> queryWrapper = new QueryWrapper<>();
//        queryWrapper
//                .eq("c_code", code)
//                .eq("c_deleted", 0);
//        Task task = baseMapper.selectOne(queryWrapper);
//        if (ObjectUtils.isEmpty(task)) {
//            return ResponseResult.error("任务码不正确！");
//        }
//        // 是否过期
//        if (task.getEndTime().isBefore(LocalDateTime.now()) || task.getStatus() == 1) {
//            return ResponseResult.error("该点餐已截止！");
//        }
//        return ResponseResult.success(task.getCode());
//    }

    /**
     * 根据订单id获取商家信息
     *
     * @param taskId
     * @return
     */
    @Override
    public StoreInfoVO getStoreInfo(String taskId) {
        QueryWrapper<Task> queryWrapper = new QueryWrapper<>();
        queryWrapper
                .eq("c_deleted", 0)
                .eq("c_task_id", taskId);
        Task task = baseMapper.selectOne(queryWrapper);
        // 处理图片
//        if (ArrayUtils.isNotEmpty(vo.getImg())) {
//            String avatarBase64 = ImgUtil.toBase64(ImgUtil.toImage(vo.getImg()), "png");
//            vo.setImgVO(avatarBase64);
//            vo.setImg(null);
//        }
        return storeInfoService.getDetail(task.getStoreId());
    }

    /**
     * 获得默认的点餐标题
     *
     * @return
     */
    @Override
    public ResponseResult<?> getDefaultTaskTitle() {
        LocalDateTime today = LocalDateTime.now();
        Integer count = baseMapper.getTodayCount();
        count++;
        return ResponseResult.success(today.getYear() + "年" + today.getMonthValue() + "月" + today.getDayOfMonth() + "日" + " 第" + count + "次点餐");
    }

    /**
     * 获取正在进行中的所有点餐
     *
     * @return
     */
    @Override
    public List<TaskOngoingListVO> getAllOngoingTask() {
        // 先将所有的点餐更新到最新状态
        QueryWrapper<Task> queryWrapper = new QueryWrapper<>();
        queryWrapper
                .eq("t.c_status", 0)
                .eq("t.c_deleted", 0);
        List<TaskOngoingListVO> taskOngoingListVOS = baseMapper.getAllOngoingTask(queryWrapper);

        System.out.println("taskOngoingListVOS " + taskOngoingListVOS);

        if (taskOngoingListVOS == null) {
            return null;
        }
        // 遍历查询过期
        for (TaskOngoingListVO vo : taskOngoingListVOS) {
            if (vo.getEndTime().isBefore(LocalDateTime.now())) {
                // 如果过期，更新状态
                vo.setStatus(1);
                // 避免重复查询，直接在这个集合删除过期点餐即可
                taskOngoingListVOS.remove(vo);
            }
        }
        return taskOngoingListVOS;
    }
}
